
#include "stdafx.h"
#include "JPGLoader.h"
#include "SVEDriverAPI.h"
#include "JPGMutex.h"
enum
{
	UNKNOWN,
	BASELINE = 0xC0,
	EXTENDED_SEQ = 0xC1,
	PROGRESSIVE = 0xC2
}JPG_SOF_MARKER;
int g_JPGInstance = 0;

JPGLoader::JPGLoader()
:m_imageWidth( 0 ), m_imageHeight( 0 ), m_imageData( NULL ), m_pStream( NULL ), m_bHeaderRead( FALSE ), m_numOfComponents( 3 )
, m_depth( 0 ), m_lineStride( 0 ), m_handle( NULL ), m_fileName( NULL ), m_rotateDegree( 0 )
{

}
JPGLoader::~JPGLoader()
{
	
}

HRESULT JPGLoader::LoadImage(const TCHAR *fileName )
{
	if( !IsJPGFile( fileName ) )
	{
		return E_UNEXPECTED;
	}

	HRESULT hrRet = CreateStreamOnFile( fileName, &m_pStream);
	ImageInfo imageInfo;
	hrRet = GetImageInfo( &imageInfo );
	return hrRet;
}
HRESULT JPGLoader::InitDecode()
{
// 	while ( g_JPGInstance != 0 )
// 	{
// 		DEBUGMSG( 1, ( TEXT( " instance is %d   &&&&&&&&&&&&&&\n"), g_JPGInstance ) );
// 	}

	return S_OK;
}
HRESULT JPGLoader::Decode( const TCHAR *fileName,RECT *dstRect, int rotateDegree, RECT *srcRect /* = NULL  */)
{
//   	DWORD			retJPG;
//   	retJPG = LockJPGMutex();
//   	if(!retJPG)
//   	{
//   		RETAILMSG(1, (TEXT("DD::JPG Mutex Lock Fail\r\n")));
//   		return E_UNEXPECTED;
//   	}
//  	HANDLE			h_Mutex;
//  	DWORD			retJPG;
//  	// Mutex initialization
//  	h_Mutex = CreateJPGmutex();
//  	if (h_Mutex == NULL)
//  	{
//  		RETAILMSG(1, (TEXT("DD::JPG Mutex Initialize error : %d \r\n"),GetLastError()));
//  		return E_UNEXPECTED;
//  	}
//  	retJPG = LockJPGMutex();
//  	if(!retJPG)
//  	{
//  		RETAILMSG(1, (TEXT("DD::JPG Mutex Lock Fail\r\n")));
//  		return E_UNEXPECTED;
//  	}
	DWORD			retJPG;
	retJPG = LockJPGMutex();
	if(!retJPG)
	{
		RETAILMSG(1, (TEXT("DD::JPG Mutex Lock Fail\r\n")));
		return E_UNEXPECTED;
	}
	m_handle = SsbSipJPEGDecodeInit();
	if(m_handle == NULL)
	{
		RETAILMSG( 1, ( TEXT("Decoder Init failed\n") ) );
		SsbSipJPEGDecodeDeInit(m_handle);
		UnlockJPGMutex();
		return E_UNEXPECTED;
	} 


 	g_JPGInstance++;
	m_dstRect.left = dstRect->left;
	m_dstRect.top = dstRect->top;
	m_dstRect.right = dstRect->right;
	m_dstRect.bottom = dstRect->bottom;
	if( srcRect == NULL )
	{
		m_srcRect.left = 0;
		m_srcRect.top = 0;
		m_srcRect.right = m_imageWidth;
		m_srcRect.bottom = m_imageHeight;
	}
	else
	{
		m_srcRect.left = srcRect->left;
		m_srcRect.top = srcRect->top;
		m_srcRect.right = srcRect->right;
		m_srcRect.bottom = srcRect->bottom;
	}
	HRESULT hr = S_OK;
	HRESULT hrRet = S_OK;
	char *InBuf = NULL;
	char *OutBuf = NULL;
	char *OutPhyBuf = NULL;
	char *OutRGBBuf = NULL;
	char *OutRGBPhyBuf = NULL;
	UINT32 fileSize = 0;
	UINT32 streamSize = 0;
	//void *handle;
	INT32 width, height, samplemode;
	JPEG_ERRORTYPE ret;

	IStream *pStream = NULL;
	hrRet = CreateStreamOnFile( fileName, &pStream);
	if( hrRet != S_OK )
	{
		RETAILMSG( 1, ( TEXT("Decoder Init failed\n") ) );
		SsbSipJPEGDecodeDeInit(m_handle);
		UnlockJPGMutex();
		return E_UNEXPECTED;
	}
	STATSTG stat;
	pStream->Stat( &stat, 0 );
	fileSize = stat.cbSize.LowPart;
	DEBUGMSG( 1,( TEXT("inBuf Size: %d\n"), fileSize ) ) ;
	InBuf = SsbSipJPEGGetDecodeInBuf(m_handle, fileSize );	
	if(InBuf == NULL)
	{
		RETAILMSG( 1,( TEXT("Input buffer is NULL\n") ) );
		SsbSipJPEGDecodeDeInit(m_handle);
		UnlockJPGMutex();
		return E_UNEXPECTED;
	}
	DEBUGMSG( 1,( TEXT("inBuf : 0x%x\n"), InBuf ) ) ;

	LARGE_INTEGER liZero = {0, 0};
	hrRet = pStream->Seek(liZero, STREAM_SEEK_SET, NULL);
	hrRet = pStream->Read( InBuf, fileSize , NULL );
	pStream->Release();
	pStream = NULL;
	if (FAILED(hrRet))
	{
		SsbSipJPEGDecodeDeInit(m_handle);
		RETAILMSG( 1,(TEXT("Exit: Read Buffer \n"), hrRet) ); 
		UnlockJPGMutex();
		return hrRet;
	}
	ret = SsbSipJPEGDecodeExe(m_handle);
	if(ret != JPEG_OK)
	{
		RETAILMSG( 1,(TEXT("Decoding failed\n") ) );
		SsbSipJPEGDecodeDeInit(m_handle);
		UnlockJPGMutex();
		return E_UNEXPECTED;	
	}

	//streamSize = width * height * 2;
	OutBuf = SsbSipJPEGGetDecodeOutBuf(m_handle, &streamSize);
	if(OutBuf == NULL)
	{
		RETAILMSG( 1, ( TEXT("Output buffer is NULL\n") ) );
		SsbSipJPEGDecodeDeInit(m_handle);
		UnlockJPGMutex();
		return E_UNEXPECTED;
	}
	DEBUGMSG( 1, ( TEXT("OutBuf : 0x%x streamsize : %d\n"), OutBuf, streamSize ) );
	SsbSipJPEGGetConfig(JPEG_GET_DECODE_WIDTH, &width);
	SsbSipJPEGGetConfig(JPEG_GET_DECODE_HEIGHT, &height);
	SsbSipJPEGGetConfig(JPEG_GET_SAMPING_MODE, &samplemode);	
	//printD("width : %d height : %d samplemode : %d\n", width, height, samplemode);	
	//DecodeFileOutYCBYCR( OutBuf, streamSize, "\\Temp\\out.yuv");
	OutPhyBuf = SsbSipJPEGGetDecodeOutPhyBuf(m_handle);
	OutRGBPhyBuf = SsbSipJPEGGetRGBPhyBuf(m_handle, m_dstRect.Width(), m_dstRect.Height());
	if(ConvertYCBYCRToRGB((int)OutPhyBuf, width, height, 
		POST_SRC_YUV422_CRYCBY,
		(int)OutRGBPhyBuf, m_dstRect.Width(), m_dstRect.Height(),
		POST_DST_RGB16) == FALSE)
	{
		RETAILMSG( 1, ( TEXT("ConvertYCBYCRToRGB error\n") ) );
		SsbSipJPEGDecodeDeInit(m_handle);
		UnlockJPGMutex();
   		//UnlockJPGMutex();   		
		return E_UNEXPECTED;
	}
	if( rotateDegree == 0 )
	{
		m_imageData = SsbSipJPEGGetRGBBuf(m_handle, m_dstRect.Width(), m_dstRect.Height());
		m_rotateDegree = rotateDegree;
	}
	else
	{
		char *outRGBRotatePhyBuf = SsbSipJPEGGetRGBRotatePhyBuf( m_handle, m_dstRect.Width(), m_dstRect.Height() );
		if( RotateJPG( (int)OutRGBPhyBuf, m_dstRect.Width(), m_dstRect.Height(), ROT_FORMAT_RGB565, ( int ) outRGBRotatePhyBuf, rotateDegree ) == FALSE )
		{
			RETAILMSG( 1, ( TEXT("RotateJPG error\n") ) );
			SsbSipJPEGDecodeDeInit(m_handle);	
			UnlockJPGMutex();
			return E_UNEXPECTED;
		}
		m_imageData = SsbSipJPEGGetRGBRotateBuf( m_handle, m_dstRect.Width(), m_dstRect.Height() );
		m_rotateDegree = rotateDegree;
	}

 	UnlockJPGMutex();
// 	BITMAPINFO bitmapInfo;
// 	bitmapInfo.bmiHeader.biBitCount = 16;
// 	bitmapInfo.bmiHeader.biClrImportant = 0;
// 	bitmapInfo.bmiHeader.biClrUsed = 0;
// 	bitmapInfo.bmiHeader.biCompression = BI_RGB;
// 	bitmapInfo.bmiHeader.biWidth = m_dstRect.Width();
// 	bitmapInfo.bmiHeader.biHeight = m_dstRect.Height();
// 	bitmapInfo.bmiHeader.biPlanes = 1;
// 	bitmapInfo.bmiHeader.biSize = sizeof( BITMAPINFOHEADER );
// 	bitmapInfo.bmiHeader.biSizeImage = 0;
// 	bitmapInfo.bmiColors[ 0 ].rgbBlue = 0;
// 	bitmapInfo.bmiColors[ 0 ].rgbGreen = 0;
// 	bitmapInfo.bmiColors[ 0 ].rgbRed = 0;
// 	bitmapInfo.bmiColors[ 0 ].rgbReserved = 0;
	// 	ret1= ::WriteFile( hFile, &bitmapInfo,sizeof( BITMAPINFOHEADER ), &dwWriten, NULL );
	// 	::WriteFile( hFile, (BYTE*)m_imageData, 480*720*2, &dwWriten, NULL );
	// 	CloseHandle( hFile );
	//SsbSipJPEGDecodeDeInit(m_handle);
	
	return hr;
}
void JPGLoader::Release()
{
// 	DWORD			retJPG;
// 	retJPG = LockJPGMutex();
// 	if(!retJPG)
// 	{
// 		RETAILMSG(1, (TEXT("DD::JPG Mutex Lock Fail\r\n")));		
// 	}
	if( m_pStream )
	{
		m_pStream->Release();
		m_pStream = NULL;
	}
	SsbSipJPEGDecodeDeInit(m_handle);
	m_imageData = NULL;
	g_JPGInstance--;	
	DEBUGMSG( 1, ( TEXT("Release JPG\n") ) );
	//UnlockJPGMutex();
}
HRESULT JPGLoader::Draw(HDC hdc )
{
//  	DWORD			retJPG;
//  	retJPG = LockJPGMutex();
//  	if(!retJPG)
//  	{
//  		RETAILMSG(1, (TEXT("DD::JPG Mutex Lock Fail\r\n")));
//  		return E_UNEXPECTED;
//  	}
	HRESULT hr = S_OK;
	HDC winDC = GetDC( NULL );
	HDC memDC = CreateCompatibleDC( winDC );
	DEBUGMSG(1, (TEXT("Image Data is 0x%x\r\n"), m_imageData ) );		
	HBITMAP hBmp = NULL;
	if( m_rotateDegree ==  90 || m_rotateDegree == 270 )
	{
		hBmp = CreateBitmap( m_dstRect.Height(), m_dstRect.Width(), 1, 16, m_imageData );//CreateDIBSection( memDC, &bitmapInfo,DIB_RGB_COLORS, (void **)&OutRGBBuf, NULL, 0 );
		if( hBmp == NULL )
		{
			hr = E_UNEXPECTED;
		}
		HGDIOBJ hOldBmp = SelectObject( memDC, hBmp );
		BitBlt( hdc, m_dstRect.top, m_dstRect.left, m_dstRect.Height(), m_dstRect.Width(), memDC, 0, 0, SRCCOPY );
		SelectObject( memDC, hOldBmp );
		DeleteObject( hBmp );
		DeleteDC( memDC );
		ReleaseDC( NULL, winDC );
	}
	else
	{
		hBmp = CreateBitmap( m_dstRect.Width(), m_dstRect.Height(), 1, 16, m_imageData );//CreateDIBSection( memDC, &bitmapInfo,DIB_RGB_COLORS, (void **)&OutRGBBuf, NULL, 0 );
		if( hBmp == NULL )
		{
			hr = E_UNEXPECTED;
		}
		HGDIOBJ hOldBmp = SelectObject( memDC, hBmp );
		BitBlt( hdc, m_dstRect.left, m_dstRect.top, m_dstRect.Width(), m_dstRect.Height(), memDC, 0, 0, SRCCOPY );
		SelectObject( memDC, hOldBmp );
		DeleteObject( hBmp );
		DeleteDC( memDC );
		ReleaseDC( NULL, winDC );
	}

//	UnlockJPGMutex();
// 	HANDLE	hFile = CreateFile(L"\\Temp\\test.bmp",GENERIC_WRITE|GENERIC_READ,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,CREATE_ALWAYS,
// 		FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM,NULL);
// 	if( hFile == INVALID_HANDLE_VALUE)
// 	{
// 		return FALSE;
// 	}
// 	//			const UInt8 BmpID[] = { 0x42, 0x4d };
// 	DWORD dwWriten = 0;
// 	//			BOOL ret1 = ::WriteFile( hFile, &BmpID,sizeof( BmpID ), &dwWriten, NULL );
// 	BITMAPFILEHEADER bitmapFileHeader;
// 	bitmapFileHeader.bfType = 19778;//0x4d42
// 	bitmapFileHeader.bfSize = 54 + 480*720*2;
// 	bitmapFileHeader.bfOffBits = 54; 
// 	BOOL ret1= ::WriteFile( hFile, &bitmapFileHeader,sizeof( BITMAPFILEHEADER ), &dwWriten, NULL );
// 

	return hr;
}
HRESULT JPGLoader::GetImageInfo(ImageInfo *imageInfo )
{
//	HRESULT hr;

	if (IsBadWritePtr(imageInfo, sizeof(ImageInfo)))
	{
		return E_POINTER;
	}
// 	if (!m_bHeaderRead)
// 	{
// 		hr = ReadHeader();
// 		if (FAILED(hr))
// 		{
// 			return hr;
// 		}
// 	}
	memset(imageInfo, 0x00, sizeof(ImageInfo));
	imageInfo->RawDataFormat = IMGFMT_JPEG;
	if( m_numOfComponents == 3 )
	{
		imageInfo->PixelFormat = PixelFormat24bppRGB;
		m_depth = 24;
	}
	if ( m_numOfComponents == 4 )
	{
		imageInfo->PixelFormat = PixelFormat32bppRGB;
		m_depth = 32;
	}
	imageInfo->Width = m_imageWidth;
	imageInfo->Height = m_imageHeight;
	imageInfo->TileWidth = imageInfo->Width;
	imageInfo->TileHeight = imageInfo->Height;
	imageInfo->Xdpi = imageInfo->Ydpi = 96;
	imageInfo->Flags = SinkFlagsTopDown | 
		SinkFlagsFullWidth |
		ImageFlagsHasAlpha |
		ImageFlagsColorSpaceRGB;
	return S_OK;
}
HRESULT JPGLoader::ReadHeader()
{
	HRESULT hr;
	LARGE_INTEGER liZero = {0, 0};
	const int c_iHeaderLength = 9;
	const int makerIdentifierlen = 2;	
	BYTE SOF0[] = { 0xFF, 0xC0 };
	// The header for the sample image format.
	BYTE rgbExpectedHeader[] = {0xFF, 0xD8};  //////////////////////////////////////////JPEG SOI Label
	// The mask for the header. The fourth byte in the header is a don't care.
	// It would also be possible to make the header case-insensitive by 
	// substituting 0xDF for the first three bytes of the mask.
	BYTE rgbHeaderMask[] = {0xFF, 0xFF};
	BYTE makerBuffer[makerIdentifierlen];
	BYTE makerlengthBuffer[ 2 ] = { 0 };

	// Reset the stream to the beginning.
	hr = m_pStream->Seek(liZero, STREAM_SEEK_SET, NULL);
	if (FAILED(hr))
	{		
		return hr;
	}

	// Read in the header for JPEG format.
	// Format: 
	// Read SOI marker: 0xFF, 0xD8
	// Read SOF marker: 0xFF, 0xC0 to get the image information
	hr = m_pStream->Read((void*)makerBuffer, makerIdentifierlen, NULL);
	if (FAILED(hr))
	{
		return hr;
	}

	for (int i = 0; i < sizeof(rgbExpectedHeader)/sizeof(*rgbExpectedHeader); i++ )
	{
		if ( (makerBuffer[i] & rgbHeaderMask[i]) != rgbExpectedHeader[i] )
		{
			return E_FAIL;
		}
	}
	BOOL findSOF = FALSE;
	while ( !findSOF )
	{
		hr = m_pStream->Read((void*)makerBuffer, makerIdentifierlen, NULL);
		if (FAILED(hr))
		{
			return hr;
		}
		if ( (makerBuffer[ 0 ] ) != 0xFF  )
		{	
			hr = m_pStream->Read((void*)makerlengthBuffer, 2, NULL);
			if (FAILED(hr))
			{
				return hr;
			}
			int makerlength = 0;
			makerlength = ( makerlengthBuffer[ 0 ] << 8 ) + makerlengthBuffer[ 1 ];
			liZero.LowPart = makerlength - 2;//2 bytes of maker length
			hr = m_pStream->Seek(liZero, STREAM_SEEK_CUR, NULL);
			if (FAILED(hr))
			{
				return hr;
			}
		}
		else
		{
			if(  ( makerBuffer[ 1 ] ) == BASELINE || ( makerBuffer[ 1 ] ) == EXTENDED_SEQ || ( makerBuffer[ 1 ] ) == PROGRESSIVE  )
			{
				findSOF = TRUE;
				const int bytesToRead = 8;// 2 bytes maker length, 1 byte data precision(bits/sample), 2 bytes image height, 2 bytes image width, 1 byte number of components
				BYTE byteRead[ bytesToRead ] = { 0 };
				hr = m_pStream->Read((void*)byteRead, bytesToRead, NULL);
				if (FAILED(hr))
				{
					
					return hr;
				}
				m_imageHeight = ( byteRead[ 3 ] << 8 ) + byteRead[ 4 ];
				m_imageWidth = ( byteRead[ 5 ] << 8 ) + byteRead[ 6 ];
				m_numOfComponents = byteRead[ 7 ];
			}
			else
			{
				hr = m_pStream->Read((void*)makerlengthBuffer, 2, NULL);
				if (FAILED(hr))
				{
					
					return hr;
				}
				int makerlength = 0;
				makerlength = ( makerlengthBuffer[ 0 ] << 8 ) + makerlengthBuffer[ 1 ];
				liZero.LowPart = makerlength - 2;//2 bytes of maker length
				hr = m_pStream->Seek(liZero, STREAM_SEEK_CUR, NULL);
				if (FAILED(hr))
				{
					 
					return hr;
				}
			}

		}

	}
	m_bHeaderRead = TRUE;	
	return S_OK;
}

void JPGLoader::initDecodeParam()
{
	m_jCtx = (JPG_CTX *)malloc(sizeof(JPG_CTX));
	memset(m_jCtx, 0x00, sizeof(JPG_CTX));

	m_jCtx->decParam = (JPG_DEC_PROC_PARAM *)malloc(sizeof(JPG_DEC_PROC_PARAM));
	memset(m_jCtx->decParam, 0x00, sizeof(JPG_DEC_PROC_PARAM));

	m_jCtx->debugPrint = TRUE;
	m_jCtx->decParam->decType = JPG_MAIN;

}

void *JPGLoader::SsbSipJPEGDecodeInit()
{
	void *JPGHandle;

	initDecodeParam();
	JPGHandle = CreateFile(JPG_DRIVER_NAME,
		GENERIC_READ|GENERIC_WRITE,
		0,
		NULL,
		OPEN_EXISTING,
		FILE_ATTRIBUTE_NORMAL,NULL);
	if(JPGHandle == INVALID_HANDLE_VALUE){
		RETAILMSG(1, (TEXT("API :: CreateFile failed\r\n")));
		return NULL;
	}

	return JPGHandle;
}
char *JPGLoader::SsbSipJPEGGetDecodeInBuf(void *openHandle, long size)
{
	int ret;

	if(size < 0 || size > MAX_FILE_SIZE){
		RETAILMSG(1, (TEXT("API :: Invalid Decoder input buffer size\r\n")));
		return NULL;
	}
	//RETAILMSG(1, ( TEXT("Size = %d \n"), size ) );
	m_jCtx->decParam->fileSize = size;

	ret = DeviceIoControl(openHandle, IOCTL_JPG_GET_STRBUF, NULL, 
		0, &(m_jCtx->InBuf), sizeof(m_jCtx->InBuf), NULL, NULL);
	if(ret == 0){
		RETAILMSG(1, (TEXT("API :: IOCTL_JPG_GET_STRBUF failed\r\n")));
		return NULL;
	}
	//RETAILMSG(1, ( TEXT("fileSize = %d \n"), size ) );
	//RETAILMSG(1, ( TEXT("API :: jCtx->InBuf(addr : %x size: %d callerProcessID : 0x%x)\n"), m_jCtx->InBuf, size, (HANDLE)GetCurrentProcessId()) );
	return (m_jCtx->InBuf);
}
char* JPGLoader::SsbSipJPEGGetDecodeOutBuf(void *openHandle, UINT32 *size)
{
	int ret;

	ret = DeviceIoControl(openHandle, IOCTL_JPG_GET_FRMBUF, NULL, 
		m_jCtx->decParam->fileSize, &(m_jCtx->OutBuf), sizeof(m_jCtx->OutBuf) , NULL, NULL);

	if(ret == 0){
		RETAILMSG(1, (TEXT("API :: GetDecodeOutBuf failed\r\n")));
		return NULL;
	}

	//printD("API :: DecodeOutBuf : 0x%x size : %d\n", m_jCtx->OutBuf, m_jCtx->decParam->dataSize);
	*size = m_jCtx->decParam->dataSize;
	return (m_jCtx->OutBuf);
}
char *JPGLoader::SsbSipJPEGGetDecodeOutPhyBuf(void *openHandle)
{
	//HANDLE	hJpegDrv = INVALID_HANDLE_VALUE;
	char	*phy_addr_frame;
	int ret;
	ret = DeviceIoControl(openHandle, IOCTL_JPG_GET_PHY_FRMBUF, NULL, 0, &phy_addr_frame, sizeof(phy_addr_frame), NULL, NULL);
	if(ret == 0){
		RETAILMSG(1, (TEXT("API :: IOCTL_JPG_GET_PHY_FRMBUF failed\r\n")));
		return NULL;
	}

	//printD("phy_addr_frame : 0x%x\n", phy_addr_frame);
	return phy_addr_frame;
}
char *JPGLoader::SsbSipJPEGGetRGBRotatePhyBuf(void *openHandle, INT32 width, INT32 height)
{
	// 	HANDLE	hJpegDrv = INVALID_HANDLE_VALUE;
	int ret;
	char	*phy_addr_rgb;
	INT32	RGBSize;

	RGBSize = width*height*2;
	if(RGBSize > MAX_JPG_WIDTH*MAX_JPG_HEIGHT*2){
		RETAILMSG(1, (TEXT("API :: RGB width and height is too big\r\n")));
		return NULL;
	}

	ret = DeviceIoControl(openHandle, IOCTL_JPG_GET_PHY_RGBBUF_ROTATE, NULL, 0, &phy_addr_rgb, sizeof(phy_addr_rgb), NULL, NULL);
	if(ret == 0){
		RETAILMSG(1, (TEXT("API :: IOCTL_JPG_GET_PHY_RGBBUF_ROTATE failed\r\n")));
		return NULL;
	}

	//printD("phy_addr_rgb : 0x%x\n", phy_addr_rgb);
	return phy_addr_rgb;
}
char *JPGLoader::SsbSipJPEGGetRGBPhyBuf(void *openHandle, INT32 width, INT32 height)
{
	// 	HANDLE	hJpegDrv = INVALID_HANDLE_VALUE;
	int ret;
	char	*phy_addr_rgb;
	INT32	RGBSize;

	RGBSize = width*height*2;
	if(RGBSize > MAX_JPG_WIDTH*MAX_JPG_HEIGHT*2){
		RETAILMSG(1, (TEXT("API :: RGB width and height is too big\r\n")));
		return NULL;
	}

	ret = DeviceIoControl(openHandle, IOCTL_JPG_GET_PHY_RGBBUF, NULL, 0, &phy_addr_rgb, sizeof(phy_addr_rgb), NULL, NULL);
	if(ret == 0){
		RETAILMSG(1, (TEXT("API :: IOCTL_JPG_GET_PHY_RGBBUF failed\r\n")));
		return NULL;
	}

	//printD("phy_addr_rgb : 0x%x\n", phy_addr_rgb);
	return phy_addr_rgb;
}
char *JPGLoader::SsbSipJPEGGetRGBRotateBuf(void *openHandle, INT32 width, INT32 height)
{
	//	HANDLE	hJpegDrv = INVALID_HANDLE_VALUE;
	int ret;
	char	*addr_rgb;
	INT32	RGBSize;

	RGBSize = width*height*2;
	if(RGBSize > 1600*1200*2/*MAX_RGB_WIDTH*MAX_RGB_HEIGHT*2*/){
		RETAILMSG(1, (TEXT("API :: RGB width and height is too big\r\n")));
		return NULL;
	}

	ret = DeviceIoControl(openHandle, IOCTL_JPG_GET_RGBBUF_ROTATE, NULL, 0, &addr_rgb, sizeof(addr_rgb), NULL, NULL);
	if(ret == 0){
		RETAILMSG(1, (TEXT("API :: IOCTL_JPG_GET_RGBBUF_ROTATE failed\r\n")));
		return NULL;
	}

	//printD("addr_rgb : 0x%x\n", addr_rgb);
	return addr_rgb;
}
char *JPGLoader::SsbSipJPEGGetRGBBuf(void *openHandle, INT32 width, INT32 height)
{
	//	HANDLE	hJpegDrv = INVALID_HANDLE_VALUE;
	int ret;
	char	*addr_rgb;
	INT32	RGBSize;

	RGBSize = width*height*2;
	if(RGBSize > 1600*1200*2/*MAX_RGB_WIDTH*MAX_RGB_HEIGHT*2*/){
		RETAILMSG(1, (TEXT("API :: RGB width and height is too big\r\n")));
		return NULL;
	}

	ret = DeviceIoControl(openHandle, IOCTL_JPG_GET_RGBBUF, NULL, 0, &addr_rgb, sizeof(addr_rgb), NULL, NULL);
	if(ret == 0){
		RETAILMSG(1, (TEXT("API :: IOCTL_JPG_GET_RGBBUF failed\r\n")));
		return NULL;
	}

	//printD("addr_rgb : 0x%x\n", addr_rgb);
	return addr_rgb;
}
char *JPGLoader::SsbSipJPEGGetOriginalRGBPhyBuf( void *openHandle, INT32 width, INT32 height )
{
	int ret;
	char	*addr_rgb;
	INT32	RGBSize;

	RGBSize = width*height*2;
	if(RGBSize > 1600*1200*2){
		RETAILMSG(1, (TEXT("API :: RGB width and height is too big\r\n")));
		return NULL;
	}

	ret = DeviceIoControl(openHandle, IOCTL_JPG_GET_PHY_RGBBUF_ROTATE, NULL, 0, &addr_rgb, sizeof(addr_rgb), NULL, NULL);
	if(ret == 0){
		RETAILMSG(1, (TEXT("API :: IOCTL_JPG_GET_RGBBUF failed\r\n")));
		return NULL;
	}

	//printD("addr_rgb : 0x%x\n", addr_rgb);
	return addr_rgb;
}
char *JPGLoader::SsbSipJPEGGetOriginalRGBBuf(void *openHandle, INT32 width, INT32 height )
{
	int ret;
	char	*addr_rgb;
	INT32	RGBSize;

	RGBSize = width*height*2;
	if(RGBSize > 1600*1200*2){
		RETAILMSG(1, (TEXT("API :: RGB width and height is too big\r\n")));
		return NULL;
	}

	ret = DeviceIoControl(openHandle, IOCTL_JPG_GET_STRBUF, NULL, 0, &addr_rgb, sizeof(addr_rgb), NULL, NULL);
	if(ret == 0){
		RETAILMSG(1, (TEXT("API :: IOCTL_JPG_GET_RGBBUF_ROTATE failed\r\n")));
		return NULL;
	}

	//printD("addr_rgb : 0x%x\n", addr_rgb);
	return addr_rgb;

}
char *JPGLoader::SsbSipJPEGGetOriginalRGBRotatePhyBuf(void *openHandle, INT32 width, INT32 height )
{
	char	*phy_addr_frame;
	int ret;
	ret = DeviceIoControl(openHandle, IOCTL_JPG_GET_PHY_FRMBUF, NULL, 0, &phy_addr_frame, sizeof(phy_addr_frame), NULL, NULL);
	if(ret == 0){
		RETAILMSG(1, (TEXT("API :: IOCTL_JPG_GET_PHY_FRMBUF failed\r\n")));
		return NULL;
	}

	//printD("phy_addr_frame : 0x%x\n", phy_addr_frame);
	return phy_addr_frame;
}
char *JPGLoader::SsbSipJPEGGetOriginalRGBRotateBuf(void *openHandle, INT32 width, INT32 height )
{
	int ret;

	ret = DeviceIoControl(openHandle, IOCTL_JPG_GET_FRMBUF, NULL, 
		m_jCtx->decParam->fileSize, &(m_jCtx->OutBuf), sizeof(m_jCtx->OutBuf) , NULL, NULL);

	if(ret == 0){
		RETAILMSG(1, (TEXT("API :: GetDecodeOutBuf failed\r\n")));
		return NULL;
	}
	return (m_jCtx->OutBuf);
}
JPEG_ERRORTYPE JPGLoader::SsbSipJPEGDecodeExe(void *openHandle)
{
	int	ret;

	//printD("API :: m_jCtx->decParam->fileSize : %d\n", m_jCtx->decParam->fileSize);
	if(m_jCtx->decParam->decType == JPG_MAIN){
		ret = DeviceIoControl(openHandle, IOCTL_JPG_DECODE, NULL, 
			0, NULL, 0, 
			(PDWORD)m_jCtx->decParam, NULL);
		if(ret == 0){
			RETAILMSG(1, (TEXT("API :: IOCTL_JPG_DECODE failed\r\n")));
			return JPEG_FAIL;
		}

		//printD("API :: decParam->width : %d decParam->height : %d\n", m_jCtx->decParam->width, m_jCtx->decParam->height);
		//printD("API :: streamSize : %d\n", m_jCtx->decParam->dataSize);
	}
	else{
		// thumbnail decode, for the future work.
	}

	return JPEG_OK;
}
JPEG_ERRORTYPE JPGLoader::SsbSipJPEGGetConfig(JPEGConf type, INT32 *value)
{
	JPEG_ERRORTYPE result = JPEG_OK;

	switch(type)
	{
	case JPEG_GET_DECODE_WIDTH: *value = (INT32)m_jCtx->decParam->width; break;
	case JPEG_GET_DECODE_HEIGHT: *value = (INT32)m_jCtx->decParam->height; break;
	case JPEG_GET_SAMPING_MODE: *value = (INT32)m_jCtx->decParam->sampleMode; break;
	default : /*printD("Invalid Config type\n")*/; result = JPEG_FAIL;
	}

	return result;
}
JPEG_ERRORTYPE JPGLoader::SsbSipJPEGDecodeDeInit(void *openHandle)
{
	if( openHandle )
	{
		CloseHandle(openHandle);
		openHandle = NULL;
		if( m_jCtx )
		{
			if(m_jCtx->decParam != NULL)
			{
				free(m_jCtx->decParam);
				m_jCtx->decParam = NULL;
			}
			free(m_jCtx);
			m_jCtx = NULL;
		}
	}
	return JPEG_OK;
}
BOOL JPGLoader::ConvertYCBYCRToRGB(int inBuf, INT32 srcwidth, INT32 srcheight, 
								  unsigned long srcType,
								  int outBuf, INT32 dstwidth, INT32 dstheight,
								  unsigned long dstType, INT32 srcOffsetX, INT32 srcOffsetY)
{
	HANDLE hPostDrv = INVALID_HANDLE_VALUE;
	SVEARG_POST_PARAMETER tParamPost;
	SVEARG_POST_BUFFER tParamBuffer;
	DWORD dwBytes;

	hPostDrv = CreateFile( L"VDE0:", GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
	if (hPostDrv == INVALID_HANDLE_VALUE)
	{
		RETAILMSG(1,(L"[VDE:ERR] VDE0 Open Device Failed\n"));
		return FALSE;
	}
	//RETAILMSG(1,(L"[VDE:ERR] IOCTL_SVE_RSC_REQUEST_POST , 0x%x\n", IOCTL_SVE_RSC_REQUEST_POST));
	// Request Post Processor H/W Resource to Video Engine Driver for Local Path
	if ( !DeviceIoControl(hPostDrv, IOCTL_SVE_RSC_REQUEST_POST, NULL, 0, NULL, 0, &dwBytes, NULL) )
	{
		RETAILMSG(1,(L"[VDE:ERR] IOCTL_SVE_RSC_REQUEST_POST Failed, 0x%x\n", IOCTL_SVE_RSC_REQUEST_POST));
		CloseHandle(hPostDrv);
		return	FALSE;
	}

	tParamPost.dwOpMode = POST_PER_FRAME_MODE;
	tParamPost.dwScanMode = POST_PROGRESSIVE;
	tParamPost.dwSrcType = srcType;
	tParamPost.dwSrcBaseWidth = srcwidth;
	tParamPost.dwSrcBaseHeight = srcheight;
	tParamPost.dwSrcWidth = srcwidth - ( srcOffsetX << 1 );
	tParamPost.dwSrcHeight = srcheight - ( srcOffsetY << 1 );
	tParamPost.dwSrcOffsetX = srcOffsetX;
	tParamPost.dwSrcOffsetY = srcOffsetY;
	tParamPost.dwDstType = dstType;
	tParamPost.dwDstBaseWidth = dstwidth;
	tParamPost.dwDstBaseHeight = dstheight;
	tParamPost.dwDstWidth = dstwidth;
	tParamPost.dwDstHeight = dstheight;
	tParamPost.dwDstOffsetX = 0;
	tParamPost.dwDstOffsetY = 0;

	if ( !DeviceIoControl(hPostDrv, IOCTL_SVE_POST_SET_PROCESSING_PARAM, &tParamPost, sizeof(SVEARG_POST_PARAMETER), NULL, 0, &dwBytes, NULL) )
	{
		RETAILMSG(1,(L"[VDE:ERR] IOCTL_SVE_POST_SET_PROCESSING_PARAM Failed\n"));
		CloseHandle(hPostDrv);
		return FALSE;
	}

	// Source Address
	tParamBuffer.dwBufferRGBY = (DWORD)inBuf;
	tParamBuffer.dwBufferCb = tParamBuffer.dwBufferRGBY+srcwidth*srcheight;
	tParamBuffer.dwBufferCr = tParamBuffer.dwBufferCb+srcwidth*srcheight/4;
	tParamBuffer.bWaitForVSync = FALSE;

	if ( !DeviceIoControl(hPostDrv, IOCTL_SVE_POST_SET_SOURCE_BUFFER, &tParamBuffer, sizeof(SVEARG_POST_BUFFER), NULL, 0, &dwBytes, NULL) )
	{
		RETAILMSG(1,(L"[VDE:ERR] IOCTL_SVE_POST_SET_SOURCE_BUFFER Failed\n"));
		CloseHandle(hPostDrv);
		return FALSE;
	}

	// Destination Address
	tParamBuffer.dwBufferRGBY = (DWORD)outBuf;
	tParamBuffer.dwBufferCb = 0;
	tParamBuffer.dwBufferCr = 0;
	tParamBuffer.bWaitForVSync = FALSE;

	if ( !DeviceIoControl(hPostDrv, IOCTL_SVE_POST_SET_DESTINATION_BUFFER, &tParamBuffer, sizeof(SVEARG_POST_BUFFER), NULL, 0, &dwBytes, NULL) )
	{
		RETAILMSG(1,(L"[VDE:ERR] IOCTL_SVE_POST_SET_DESTINATION_BUFFER Failed\n"));
		CloseHandle(hPostDrv);
		return FALSE;
	}

	// Post Processing Start
	if ( !DeviceIoControl(hPostDrv, IOCTL_SVE_POST_SET_PROCESSING_START, NULL, 0, NULL, 0, &dwBytes, NULL) )
	{
		RETAILMSG(1,(L"[VDE:ERR] IOCTL_SVE_POST_SET_PROCESSING_START Failed\n"));
		CloseHandle(hPostDrv);
		return FALSE;
	}

	// Wait for Post Processing Finished
	if ( !DeviceIoControl(hPostDrv, IOCTL_SVE_POST_WAIT_PROCESSING_DONE, NULL, 0, NULL, 0, &dwBytes, NULL) )
	{
		RETAILMSG(1,(L"[VDE:ERR] IOCTL_SVE_POST_WAIT_PROCESSING_DONE Failed\n"));
		CloseHandle(hPostDrv);
		return FALSE;
	}

	// Release Post Processor H/W Resource to Video Engine Driver for Local Path
	if ( !DeviceIoControl(hPostDrv, IOCTL_SVE_RSC_RELEASE_POST, NULL, 0, NULL, 0, &dwBytes, NULL) )
	{
		RETAILMSG(1,(L"[VDE:ERR] IOCTL_SVE_RSC_RELEASE_POST Failed\n"));
		CloseHandle(hPostDrv);
		return FALSE;
	}

	CloseHandle(hPostDrv);

	return TRUE;


}
BOOL JPGLoader::RotateJPG(int inBuf, INT32 srcwidth, INT32 srcheight, unsigned long srcType, int outBuf, int rotateDegree )
{
	HANDLE hRotatorDrv = INVALID_HANDLE_VALUE;
	SVEARG_ROTATOR_PARAMETER tParamRotator;
	SVEARG_ROTATOR_BUFFER tParamBuffer;
	DWORD dwBytes;
	hRotatorDrv = CreateFile( L"VDE0:", GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
	if (hRotatorDrv == INVALID_HANDLE_VALUE)
	{
		RETAILMSG(1,(L"[VDE:ERR] VDE0 Open Device Failed\n"));
		return FALSE;
	}
	//RETAILMSG(1,(L"[VDE:ERR] IOCTL_SVE_RSC_REQUEST_POST , 0x%x\n", IOCTL_SVE_RSC_REQUEST_POST));
	// Request Rotator H/W Resource to Video Engine Driver for Local Path
	if ( !DeviceIoControl(hRotatorDrv, IOCTL_SVE_RSC_REQUEST_ROTATOR, NULL, 0, NULL, 0, &dwBytes, NULL) )
	{
		RETAILMSG(1,(L"[VDE:ERR] IOCTL_SVE_RSC_REQUEST_POST Failed, 0x%x\n", IOCTL_SVE_RSC_REQUEST_POST));
		CloseHandle(hRotatorDrv);
		return	FALSE;
	}
	tParamRotator.dwImgFormat = srcType;
	if( rotateDegree == 90 )
	{
		tParamRotator.dwOpType = ROT_OP_ROTATE_90;
	}
	else if( rotateDegree == 180 )
	{
		tParamRotator.dwOpType = ROT_OP_ROTATE_180;
	}
	else if( rotateDegree == 270 )
	{
		tParamRotator.dwOpType = ROT_OP_ROTATE_270;
	}
	tParamRotator.dwSrcHeight = srcheight;
	tParamRotator.dwSrcWidth = srcwidth;
	//set operation param
	if ( !DeviceIoControl(hRotatorDrv, IOCTL_SVE_ROTATOR_SET_OPERATION_PARAM, &tParamRotator, sizeof(SVEARG_ROTATOR_PARAMETER), NULL, 0, &dwBytes, NULL) )
	{
		RETAILMSG(1,(L"[VDE:ERR] IOCTL_SVE_ROTATOR_SET_OPERATION_PARAM Failed\n"));
		CloseHandle(hRotatorDrv);
		return FALSE;
	}
	//set source buffer
	tParamBuffer.dwBufferRGBY = (DWORD)inBuf;
	tParamBuffer.dwBufferCb = 0;
	tParamBuffer.dwBufferCr = 0;
	if ( !DeviceIoControl(hRotatorDrv, IOCTL_SVE_ROTATOR_SET_SOURCE_BUFFER, &tParamBuffer, sizeof(SVEARG_ROTATOR_BUFFER), NULL, 0, &dwBytes, NULL) )
	{
		RETAILMSG(1,(L"[VDE:ERR] IOCTL_SVE_ROTATOR_SET_SOURCE_BUFFER Failed\n"));
		CloseHandle(hRotatorDrv);
		return FALSE;
	}
	//set destination buffer
	tParamBuffer.dwBufferRGBY = (DWORD)outBuf;
	tParamBuffer.dwBufferCb = 0;
	tParamBuffer.dwBufferCr = 0;
	if ( !DeviceIoControl(hRotatorDrv, IOCTL_SVE_ROTATOR_SET_DESTINATION_BUFFER, &tParamBuffer, sizeof(SVEARG_ROTATOR_BUFFER), NULL, 0, &dwBytes, NULL) )
	{
		RETAILMSG(1,(L"[VDE:ERR] IOCTL_SVE_ROTATOR_SET_DESTINATION_BUFFER Failed\n"));
		CloseHandle(hRotatorDrv);
		return FALSE;
	}
	//set operation start
	if ( !DeviceIoControl(hRotatorDrv, IOCTL_SVE_ROTATOR_SET_OPERATION_START, NULL, 0, NULL, 0, &dwBytes, NULL) )
	{
		RETAILMSG(1,(L"[VDE:ERR] IOCTL_SVE_ROTATOR_SET_OPERATION_START Failed\n"));
		CloseHandle(hRotatorDrv);
		return FALSE;
	}
		Sleep( 50 );
	// Wait for Post Processing Finished
	if ( !DeviceIoControl(hRotatorDrv, IOCTL_SVE_ROTATOR_WAIT_OPERATION_DONE, NULL, 0, NULL, 0, &dwBytes, NULL) )
	{
		RETAILMSG(1,(L"[VDE:ERR] IOCTL_SVE_ROTATOR_WAIT_OPERATION_DONE Failed\n"));
		CloseHandle(hRotatorDrv);
		return FALSE;
	}

	// Release Post Processor H/W Resource to Video Engine Driver for Local Path
	if ( !DeviceIoControl(hRotatorDrv, IOCTL_SVE_RSC_RELEASE_ROTATOR, NULL, 0, NULL, 0, &dwBytes, NULL) )
	{
		RETAILMSG(1,(L"[VDE:ERR] IOCTL_SVE_RSC_RELEASE_ROTATOR Failed\n"));
		CloseHandle(hRotatorDrv);
		return FALSE;
	}

	CloseHandle(hRotatorDrv);
	


	return TRUE;
}
HRESULT JPGLoader::Decode(HDC hdc, const TCHAR *fileName, RECT *dstRect, int rotateDegree /* = 0 */, RECT *srcRect /* = NULL  */, BOOL bDecodeOriginal )
{
	DWORD			retJPG;
	retJPG = LockJPGMutex();
	if(!retJPG)
	{
		RETAILMSG(1, (TEXT("DD::JPG Mutex Lock Fail\r\n")));
		return E_UNEXPECTED;
	}
	m_handle = SsbSipJPEGDecodeInit();
	if(m_handle == NULL)
	{
		RETAILMSG( 1, ( TEXT("Decoder Init failed\n") ) );
		SsbSipJPEGDecodeDeInit(m_handle);
		UnlockJPGMutex();
		return E_UNEXPECTED;
	} 
	m_dstRect.left = dstRect->left;
	m_dstRect.top = dstRect->top;
	m_dstRect.right = dstRect->right;
	m_dstRect.bottom = dstRect->bottom;
	if( srcRect == NULL )
	{
		m_srcRect.left = 0;
		m_srcRect.top = 0;
		m_srcRect.right = m_imageWidth;
		m_srcRect.bottom = m_imageHeight;
	}
	else
	{
		m_srcRect.left = srcRect->left;
		m_srcRect.top = srcRect->top;
		m_srcRect.right = srcRect->right;
		m_srcRect.bottom = srcRect->bottom;
	}
	HRESULT hr = S_OK;
	HRESULT hrRet = S_OK;
	char *InBuf = NULL;
	char *OutBuf = NULL;
	char *OutPhyBuf = NULL;
	char *OutRGBBuf = NULL;
	char *OutRGBPhyBuf = NULL;
	UINT32 fileSize = 0;
	UINT32 streamSize = 0;
	//void *handle;
	INT32 width, height, samplemode;
	JPEG_ERRORTYPE ret;

	IStream *pStream = NULL;
	hrRet = CreateStreamOnFile( fileName, &pStream);
	if( hrRet != S_OK )
	{
		RETAILMSG( 1, ( TEXT("Decoder Init failed\n") ) );
		SsbSipJPEGDecodeDeInit(m_handle);
		UnlockJPGMutex();
		return E_UNEXPECTED;
	}
	STATSTG stat;
	pStream->Stat( &stat, 0 );
	fileSize = stat.cbSize.LowPart;
	//DEBUGMSG( 1,( TEXT("inBuf Size: %d\n"), fileSize ) ) ;
	InBuf = SsbSipJPEGGetDecodeInBuf(m_handle, fileSize );	
	if(InBuf == NULL)
	{
		RETAILMSG( 1,( TEXT("Input buffer is NULL\n") ) );
		SsbSipJPEGDecodeDeInit(m_handle);
		UnlockJPGMutex();
		return E_UNEXPECTED;
	}
	//DEBUGMSG( 1,( TEXT("inBuf : 0x%x\n"), InBuf ) ) ;

	LARGE_INTEGER liZero = {0, 0};
	hrRet = pStream->Seek(liZero, STREAM_SEEK_SET, NULL);
	hrRet = pStream->Read( InBuf, fileSize , NULL );
	pStream->Release();
	pStream = NULL;
	if (FAILED(hrRet))
	{
		SsbSipJPEGDecodeDeInit(m_handle);
		RETAILMSG( 1,(TEXT("Exit: Read Buffer \n"), hrRet) ); 
		UnlockJPGMutex();
		return hrRet;
	}
	ret = SsbSipJPEGDecodeExe(m_handle);
	if(ret != JPEG_OK)
	{
		RETAILMSG( 1,(TEXT("Decoding failed\n") ) );
		SsbSipJPEGDecodeDeInit(m_handle);
		UnlockJPGMutex();
		return E_UNEXPECTED;	
	}

	//streamSize = width * height * 2;
	OutBuf = SsbSipJPEGGetDecodeOutBuf(m_handle, &streamSize);
	if(OutBuf == NULL)
	{
		RETAILMSG( 1, ( TEXT("Output buffer is NULL\n") ) );
		SsbSipJPEGDecodeDeInit(m_handle);
		UnlockJPGMutex();
		return E_UNEXPECTED;
	}
	//DEBUGMSG( 1, ( TEXT("OutBuf : 0x%x streamsize : %d\n"), OutBuf, streamSize ) );
	SsbSipJPEGGetConfig(JPEG_GET_DECODE_WIDTH, &width);
	SsbSipJPEGGetConfig(JPEG_GET_DECODE_HEIGHT, &height);
	SsbSipJPEGGetConfig(JPEG_GET_SAMPING_MODE, &samplemode);	
	int adjustScaleWidth = m_dstRect.Width();
	int adjustScaleHeight = m_dstRect.Height();
	int preScale_V_Ratio = 2;
	int preScale_H_Ratio = 4;
	if( width >= (adjustScaleWidth << 3) )
	{
		preScale_H_Ratio = 8;
	}
	else if( width >= ( adjustScaleWidth << 2) )
	{
		preScale_H_Ratio = 4;
	}
	else if( width >= ( adjustScaleWidth << 1 ) )
	{
		preScale_H_Ratio = 2;
	}
	else 
	{
		preScale_H_Ratio = 1;
	}
	int srcWidth_Mutiple = preScale_H_Ratio << 2;
	if( height >= ( adjustScaleHeight << 3 ) )
	{
		preScale_V_Ratio = 8;
	}
	else if( height >= ( adjustScaleHeight << 2 ) )
	{
		preScale_V_Ratio = 4;
	}
	else if( height >= ( adjustScaleHeight << 1 ) )
	{
		preScale_V_Ratio = 2;
	}
	else 
	{
		preScale_V_Ratio = 1;
	}
	int srcHeight_Mutiple = preScale_V_Ratio << 1;
	int adjustOffsetXd = width % srcWidth_Mutiple;
	int adjustOffsetYd = height % srcHeight_Mutiple;
	int srcOffsetX = adjustOffsetXd >> 1;
	int srcOffsetY = adjustOffsetYd >> 1;

	if( preScale_H_Ratio == 1 && width > 2048 )
	{
		adjustOffsetXd = width % 8;
		adjustOffsetYd = height % 4;
		srcOffsetX = adjustOffsetXd >> 1;
		srcOffsetY = adjustOffsetYd >> 1;
		adjustScaleHeight = ( height - adjustOffsetYd ) >> 1;
		adjustScaleWidth = ( width - adjustOffsetXd ) >> 1;
		if( adjustScaleWidth % 4 != 0 )
		{
			adjustScaleWidth = ( ( adjustScaleWidth + 3 ) >> 2 ) << 2;
		}
		if( rotateDegree == 90 || rotateDegree == 270 )
		{
			adjustScaleHeight = ( ( adjustScaleHeight + 3 ) >> 2 ) << 2;
		}
		bDecodeOriginal = TRUE;
	}
	//printD("width : %d height : %d samplemode : %d\n", width, height, samplemode);	
	//DecodeFileOutYCBYCR( OutBuf, streamSize, "\\Temp\\out.yuv");
	OutPhyBuf = SsbSipJPEGGetDecodeOutPhyBuf(m_handle);
	if( !bDecodeOriginal )
	{
		OutRGBPhyBuf = SsbSipJPEGGetRGBPhyBuf(m_handle, m_dstRect.Width(), m_dstRect.Height());
	}
	else
	{
		OutRGBPhyBuf = SsbSipJPEGGetOriginalRGBPhyBuf(m_handle, m_dstRect.Width(), m_dstRect.Height());
	}

	if(ConvertYCBYCRToRGB((int)OutPhyBuf, width, height, 
		POST_SRC_YUV422_CRYCBY,
		(int)OutRGBPhyBuf, adjustScaleWidth, adjustScaleHeight,
		POST_DST_RGB16, srcOffsetX, srcOffsetY ) == FALSE)
	{
		RETAILMSG( 1, ( TEXT("ConvertYCBYCRToRGB error\n") ) );
		SsbSipJPEGDecodeDeInit(m_handle);
		UnlockJPGMutex();
		//UnlockJPGMutex();   		
		return E_UNEXPECTED;
	}
	if( rotateDegree == 0 )
	{
		if( !bDecodeOriginal )
		{
			m_imageData = SsbSipJPEGGetRGBBuf(m_handle, adjustScaleWidth, adjustScaleHeight);

		}
		else
		{
			m_imageData = SsbSipJPEGGetOriginalRGBBuf( m_handle, adjustScaleWidth, adjustScaleHeight );
		}
		m_rotateDegree = rotateDegree;
	}
	else
	{
		char *outRGBRotatePhyBuf = NULL;
		if( !bDecodeOriginal )
		{
			outRGBRotatePhyBuf = SsbSipJPEGGetRGBRotatePhyBuf( m_handle, adjustScaleWidth, adjustScaleHeight );
		}
		else
		{
			outRGBRotatePhyBuf = SsbSipJPEGGetOriginalRGBRotatePhyBuf( m_handle, adjustScaleWidth, adjustScaleHeight );
		}
		if( RotateJPG( (int)OutRGBPhyBuf, adjustScaleWidth, adjustScaleHeight, ROT_FORMAT_RGB565, ( int ) outRGBRotatePhyBuf, rotateDegree ) == FALSE )
		{
			RETAILMSG( 1, ( TEXT("RotateJPG error\n") ) );
			SsbSipJPEGDecodeDeInit(m_handle);	
			UnlockJPGMutex();
			return E_UNEXPECTED;
		}
		if( !bDecodeOriginal )
		{
			m_imageData = SsbSipJPEGGetRGBRotateBuf( m_handle, adjustScaleWidth, adjustScaleHeight );
		}
		else
		{
			m_imageData = SsbSipJPEGGetOriginalRGBRotateBuf( m_handle, adjustScaleWidth, adjustScaleHeight );
		}
		m_rotateDegree = rotateDegree;
	}
	HDC winDC = GetDC( NULL );
	HDC memDC = CreateCompatibleDC( winDC );
	//DEBUGMSG(1, (TEXT("Image Data is 0x%x\r\n"), m_imageData ) );		
	HBITMAP hBmp = NULL;
	if( m_rotateDegree ==  90 || m_rotateDegree == 270 )
	{
		hBmp = CreateBitmap( adjustScaleHeight, adjustScaleWidth, 1, 16, m_imageData );//CreateDIBSection( memDC, &bitmapInfo,DIB_RGB_COLORS, (void **)&OutRGBBuf, NULL, 0 );
		if( hBmp == NULL )
		{
			hr = E_UNEXPECTED;
		}
		HGDIOBJ hOldBmp = SelectObject( memDC, hBmp );
		StretchBlt( hdc, m_dstRect.top, m_dstRect.left, m_dstRect.Height(), m_dstRect.Width(), memDC, 0, 0,  adjustScaleHeight, adjustScaleWidth,SRCCOPY );
		SelectObject( memDC, hOldBmp );
		DeleteObject( hBmp );
		DeleteDC( memDC );
		ReleaseDC( NULL, winDC );
	}
	else
	{
		hBmp = CreateBitmap( adjustScaleWidth, adjustScaleHeight, 1, 16, m_imageData );//CreateDIBSection( memDC, &bitmapInfo,DIB_RGB_COLORS, (void **)&OutRGBBuf, NULL, 0 );
		if( hBmp == NULL )
		{
			hr = E_UNEXPECTED;
		}
		HGDIOBJ hOldBmp = SelectObject( memDC, hBmp );
		StretchBlt( hdc, m_dstRect.left, m_dstRect.top, m_dstRect.Width(), m_dstRect.Height(), memDC, 0, 0, adjustScaleWidth, adjustScaleHeight, SRCCOPY );
		SelectObject( memDC, hOldBmp );
		DeleteObject( hBmp );
		DeleteDC( memDC );
		ReleaseDC( NULL, winDC );
	}	
/*	if( hOrigianlDC != NULL )
	{
		char *OutOriginalRGBPhyBuf = NULL;
		int originalWidth = srcRect->right - srcRect->left;
		int originalHeight = srcRect->bottom - srcRect->top;
		OutOriginalRGBPhyBuf = SsbSipJPEGGetOriginalRGBPhyBuf( m_handle, originalWidth, originalHeight );
		if(ConvertYCBYCRToRGB((int)OutPhyBuf, width, height, 
			POST_SRC_YUV422_CRYCBY,
			(int)OutOriginalRGBPhyBuf, originalWidth, originalHeight,
			POST_DST_RGB16) == FALSE)
		{
			RETAILMSG( 1, ( TEXT("ConvertYCBYCRToRGB error\n") ) );
			SsbSipJPEGDecodeDeInit(m_handle);
			UnlockJPGMutex();
			//UnlockJPGMutex();   		
			return E_UNEXPECTED;
		}
		char *OutOriginalRGB = NULL;
		if( rotateDegree == 0 )
		{
			OutOriginalRGB = SsbSipJPEGGetOriginalRGBBuf(m_handle, originalWidth, originalHeight);
			m_rotateDegree = rotateDegree;
		}
		else
		{
			char *outOrigianlRGBRotatePhyBuf = SsbSipJPEGGetOriginalRGBRotatePhyBuf( m_handle, originalWidth, originalHeight );
			if( RotateJPG( (int)OutRGBPhyBuf, originalWidth, originalHeight, ROT_FORMAT_RGB565, ( int ) outOrigianlRGBRotatePhyBuf, rotateDegree ) == FALSE )
			{
				RETAILMSG( 1, ( TEXT("RotateJPG error\n") ) );
				SsbSipJPEGDecodeDeInit(m_handle);	
				UnlockJPGMutex();
				return E_UNEXPECTED;
			}
			OutOriginalRGB = SsbSipJPEGGetOriginalRGBRotateBuf( m_handle, originalWidth, originalHeight );
			m_rotateDegree = rotateDegree;
		}
		HDC winDC = GetDC( NULL );
		HDC memDC = CreateCompatibleDC( winDC );
		//DEBUGMSG(1, (TEXT("Image Data is 0x%x\r\n"), m_imageData ) );		
		HBITMAP hBmp = NULL;
		if( m_rotateDegree ==  90 || m_rotateDegree == 270 )
		{
			hBmp = CreateBitmap( originalWidth, originalHeight, 1, 16, OutOriginalRGB );//CreateDIBSection( memDC, &bitmapInfo,DIB_RGB_COLORS, (void **)&OutRGBBuf, NULL, 0 );
			if( hBmp == NULL )
			{
				hr = E_UNEXPECTED;
			}
			HGDIOBJ hOldBmp = SelectObject( memDC, hBmp );
			BitBlt( hOrigianlDC, srcRect->left, srcRect->top, originalWidth, originalHeight, memDC, 0, 0, SRCCOPY );
			SelectObject( memDC, hOldBmp );
			DeleteObject( hBmp );
			DeleteDC( memDC );
			ReleaseDC( NULL, winDC );
		}
		else
		{
			hBmp = CreateBitmap( originalWidth, originalHeight, 1, 16, OutOriginalRGB );//CreateDIBSection( memDC, &bitmapInfo,DIB_RGB_COLORS, (void **)&OutRGBBuf, NULL, 0 );
			if( hBmp == NULL )
			{
				hr = E_UNEXPECTED;
			}
			HGDIOBJ hOldBmp = SelectObject( memDC, hBmp );
			BitBlt( hOrigianlDC, srcRect->left, srcRect->top, originalWidth, originalHeight, memDC, 0, 0, SRCCOPY );
			SelectObject( memDC, hOldBmp );
			DeleteObject( hBmp );
			DeleteDC( memDC );
			ReleaseDC( NULL, winDC );
		}	
	}*/
	SsbSipJPEGDecodeDeInit(m_handle);
	UnlockJPGMutex();
	return hr;
}

